<template>
  <div>
    <FromRenderer ref="FromRenderer" :cfg="cfg" />

    <div class="btns" v-if="isShowBtns">
      <Button type="primary" v-if="status === 1" @click="create">创建</Button>
      <Button type="primary" v-if="status === 2" @click="update">保存</Button>

      <Button @click="resetFields" v-if="status !== 0">重置</Button>
      <Button @click="router.back()">返回</Button>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import { get, post, put } from '../../../common/request';
import FromRenderer from "./form-factory-renderer.vue";
import { useRouter } from 'vue-router';

export default defineComponent({
  name: "FormLoader",
  setup() {
    const router = useRouter();  // 获取 router 实例
    return { router };
  },
  components: { FromRenderer },
  props: {
    // formId: { type: Number, required: false }, // 表单配置 id
    apiPrefix: { type: String, required: false },     // API 前缀
    isShowBtns: { type: Boolean, required: false, default: true }, // 是否显示按钮，还是自定义按钮？
  },
  data() {
    return {
      formId: 0, // 表单定义 id
      entityId: '', // 实体 id
      cfg: {
        labelWidth: 80, fields: [], isShowBtns: false, isRESTful_writeApi: false,
        dataBinding: {
          /**
           * 请求地址
           */
          url: "",

          /**
           * 固定参数
           */
          baseParams: "string",

          /**
           * 动态获取参数的函数
           */
          beforeRequest: ""
        }
      } as FormFactory_Config,
      status: 1, // 0=查看/1=新增/2=修改
      oldJson: null, // JSON Based 下的旧 JSON 完整数据。因为 data 只有部分
    };
  },
  mounted(): void {
    if (this.formId)
      this.load();
  },
  methods: {
    /**
     * 加载表单配置
     */
    load(): void {
      const fromRenderer: any = this.$refs.FromRenderer;

      if (this.entityId)
        // 有 id 表示修改状态
        this.status = 2;
      else {
        this.status = 1;
        (this.$refs.FromRenderer as any).data = {};
      }

      get(`${this.apiPrefix}/common_api/widget_config/${this.formId}`, (j: RepsonseResult) => {
        if (j && j.status) {
          this.cfg = j.data.config;

          const cfg: FormFactory_Config = this.cfg;
          const isJsonBased = cfg.jsonBased && cfg.jsonBased.isJsonBased;
          const dataBinding: DataBinding = cfg.dataBinding;

          if (isJsonBased) {
            this.status = 2; // JSON 配置模式下没有新建

            get(dataBinding.url, (j: RepsonseResult) => {
              // @ts-ignore
              this.oldJson = j; // 完整的

              const jsonTarget: any = findNode(this.oldJson, this.entityId.split(".")); // 部分的，目标的

              (this.$refs.FromRenderer as any).data = {};
              Object.assign(fromRenderer.data, jsonTarget);
            });

          } else {
            if (this.entityId) {// 加载单笔内容
              (this.$refs.FromRenderer as any).data = {};

              get(`${dataBinding.url}/${this.entityId}`, (j: RepsonseResult) => {
                if (isJsonBased) {
                  fromRenderer.data = j;
                  fromRenderer.$forceUpdate();
                } else {
                  const r = j.data;

                  if (r) {
                    fromRenderer.data = r;
                    fromRenderer.$forceUpdate();
                  } else
                    this.$Message.warning("获取单笔内容失败");
                }
              });
            }
          }
        } else
          this.$Message.error("获取表单配置失败");
      });
    },

    /**
     * 重置表单，但没作用
     */
    resetFields(): void {
      (this.$refs.FromRenderer as any).$refs.formDynamic.resetFields();
    },

    /**
     * 创建
     */
    create(): void {
      const cfg: FormFactory_Config = this.cfg;
      let api: DataBinding | undefined;

      const callback = (j: RepsonseResult) => {
        if (j.status) {
          this.$Message.success(j.message);
          setTimeout(() => location.hash = location.hash + '&entityId=' + j.data, 2000);
        } else
          this.$Message.error(j.message || '创建失败，原因未知！');
      };

      if (cfg.isRESTful_writeApi) {
        api = cfg.updateApi;
        const r: ManagedRequest = this._initParams(api);

        post(r.url, callback, r.params);
      } else {
        api = cfg.createApi;
        const r: ManagedRequest = this._initParams(api);

        (api?.httpMethod == 'post' ? post : put)(r.url, callback, r.params);
      }
    },

    /**
      * 更新
      */
    update(): void {
      const cfg: FormFactory_Config = this.cfg;
      const api: DataBinding | undefined = cfg.updateApi;
      const params: any = api?.baseParams || {};

      if (cfg.jsonBased?.isJsonBased) {// Raw body post
        const jsonTarget: any = findNode(this.oldJson, this.entityId.split('.'));
        Object.assign(jsonTarget, (this.$refs.FromRenderer as any).data);

        // @ts-ignore xxxx
        const json: string = JSON.stringify(r.params);
        console.log(json);

        if (api)
          post(api.url, json, (j: RepsonseResult) => {
            console.log(j)
          }, { contentType: 'application/json' });
      } else {
        const r: ManagedRequest = this._initParams(api, (this.$refs.FromRenderer as any).data, this);

        put(r.url, (j: RepsonseResult) => {
          if (j.status)
            this.$Message.success(j.message);
          else
            this.$Message.error(j.message || '更新失败，原因未知！');
        }, r.params);
      }
    }
  },
});

function findNode(obj: any, queen: string[]): any {
  if (!queen.shift)
    return null;

  const first: string | undefined = queen.shift();

  for (const i in obj) {
    if (i === first) {
      const target: any = obj[i];

      if (queen.length == 0)
        // 找到了
        return target;
      else
        return findNode(obj[i], queen);
    }
  }
}
</script>

<style lang="less" scoped>
.btns {
  text-align: center;
  padding: 20px 0;

  Button {
    width: 130px;
    letter-spacing: 3px;
    margin-right: 30px;
  }
}
</style>